using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Runtime.Remoting.Channels.Ipc;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting;
using MSRI.SmsService;
using MSRI.TCPServices;
using MSRI.HelperClasses;
using MSRI.ActiveSyncServices;
using System.Diagnostics;
using MSRI.DesktopAgent.CeRapi;

namespace MSRI.DesktopAgent
{
    public partial class AgentForm : Form
    {
        public IDccMan objIDccMan;
        DccManSink objDccManSink;
        private TcpClientClass tcpClient;
        private int AdviceReturn = 0;
        delegate void MessageReceivedDelegate(string Message);
        delegate void StatusUpdateDelegate(string Message);
        delegate void MessageHistoryUpdateDelegate(string Message);
        delegate void InboxTableUpdateDelegate(SmsClass Message);
        delegate void SentTableUpdateDelegate(String ClientName, SmsClass Message);
        delegate void ClientComboBoxUpdateDelegate();
        delegate void DeliveryReportStatusUpdateDelegate(DeliveryReportClass Report);
        delegate void ReStartDelegate();
        private SmsPublishClass IPCPublisher = null;
        private IpcChannel ipc = null;
        int IsActiveSyncConnected = 0;
        private string EmulatorClientName = null;
        private bool EmulatorStarted = false;
        private Config ConfigForm = null;
        private SendSmsForm sendSmsForm = null;
        private AboutBox AboutForm = null;
        public AgentForm()
        {
            InitializeComponent();
            this.AgentInit();
        }

        private void AgentInit()
        {
            StatusUpdate("Initializing Desktop Agent");
            MessageHistoryBox.Text = "";
            Application.DoEvents();
            //
            // Init IPC channel
            //
            
            BinaryServerFormatterSinkProvider serverProv = new BinaryServerFormatterSinkProvider();
            serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
            BinaryClientFormatterSinkProvider clientProv = new BinaryClientFormatterSinkProvider();

            System.Collections.Hashtable properties = new System.Collections.Hashtable();
            properties["name"] = "MSRI_Sms_Server";
            properties["portName"] = "MSRI_Sms_Server";
            properties["exclusiveAddressUse"] = false;
            properties["socketCacheTimeout"] = "-1";
            properties["connectionTimeout"] = "-1";
            properties["timeout"] = "-1";
            properties["typeFilterLevel"] = "Full";
            ipc = new IpcChannel(properties, clientProv, serverProv);
            ChannelServices.RegisterChannel(ipc, false);

            RemotingConfiguration.RegisterWellKnownServiceType(
                typeof(SmsPublishClass), "MSRI_Sms_Server.rem", WellKnownObjectMode.Singleton);
            IPCPublisher = (SmsPublishClass)Activator.GetObject(typeof(SmsPublishClass), "ipc://MSRI_Sms_Server/MSRI_Sms_Server.rem");
            IPCPublisher.OnClientSendSms += new OnSendSmsDelegate(IPCPublisher_OnClientSendSms);
            IPCPublisher.OnClientSendMessage += new OnSendMessageDelegate(IPCPublisher_OnClientSendMessage);
            IPCPublisher.OnClientConnected += new OnConnectedDelegate(IPCPublisher_OnClientConnected);
            IPCPublisher.OnClientDisconnected += new OnConnectedDelegate(IPCPublisher_OnClientDisconnected);

            //
            //Init TCP channel for Smartphone
            //

            tcpClient = new TcpClientClass();
            tcpClient.MessageReceived += new TcpClientClass.MessageReceivedDelegate(tcpClient_MessageReceived);
            tcpClient.Disconnected += new TcpClientClass.DisconnectedDelegate(tcpClient_Disconnected);
            tcpClient.Connected += new TcpClientClass.ConnectedDelegate(tcpClient_Connected);
            tcpClient.SmsReceived += new TcpClientClass.SmsReceivedDelegate(tcpClient_SmsReceived);
            tcpClient.DeliveryReportReceived += new TcpClientClass.DeliveryReportReceivedDelegate(tcpClient_DeliveryReportReceived);
            
            //
            //Init ActiveSync For Smartphone
            //

            DccMan objDccMan = new DccMan();
            objIDccMan = objDccMan as IDccMan;
            objDccManSink = new DccManSink();
            objDccManSink.Active += new DccManSink.ActiveHandler(objDccManSink_Active);
            objDccManSink.Disconnect += new DccManSink.DisconnectHandler(objDccManSink_Disconnect);
            objDccManSink.ConnectedToIPaddress += new DccManSink.OnLogIpAddrHandler(objDccManSink_ConnectedToIPaddress);
            FolderTabControl.TabPages["EmulatorTab"].Enter += new EventHandler(EmulatorTab_Enter);

            EmulatorStarted = false;
            StatusUpdate("ActiveSync Disconnected");

            objIDccMan.Advise(objDccManSink, ref AdviceReturn);


        }

        void tcpClient_DeliveryReportReceived(DeliveryReportClass Report)
        {
            DeliveryReportStatusUpdate(Report);
        }

        void IPCPublisher_OnClientDisconnected(string name)
        {
            ClientComboBoxUpdate();
        }

        void IPCPublisher_OnClientConnected(string name)
        {
            ClientComboBoxUpdate();
        }

        void IPCPublisher_OnClientSendMessage(string ClientName, string Message)
        {
            
        }

        void IPCPublisher_OnClientSendSms(string ClientName, SmsClass Message)
        {
            if (ClientName == EmulatorClientName)
            {
                string str = String.Format("\\b Sent:\\b0 {0} " +
                            "\\par\\b From:\\b0 {1}" +
                            "\\par\\b To:\\b0 {2}" +
                            "\\par\\b Message({3}):\\b0\\par {4}" +
                            "\\par __________________________________", Message.Time, EmulatorClientName, Message.Number, Message.Body.Length, Message.Body);
                str = str.Replace("\n", "\\par ");
                MessageHistoryUpdate(str);
                //DeliveryReportClass report = new DeliveryReportClass();
                //report.MessageID = Message.MessageID;
                //report.Status = DeliveryStatusEnum.Sent;
                //IPCPublisher.Server2Client_DeliveryReportReceived(ClientName, report, true);
            }
            else
            {
                SentTableUpdate(ClientName, Message);
            }
        }

        void EmulatorTab_Enter(object sender, EventArgs e)
        {
            ClientComboBoxUpdate();
        }

        void StatusUpdate(string Message)
        {
            if (InvokeRequired)
            {
                Invoke(new StatusUpdateDelegate(StatusUpdate), new object[] { Message });
            }
            else
            {
                ConnectionStatusLabel.Text = Message;
            }
        }

        void ClientComboBoxUpdate()
        {
            if (InvokeRequired)
            {
                Invoke(new ClientComboBoxUpdateDelegate(ClientComboBoxUpdate), new object[] {});
            }
            else
            {
                List<string> clientname = new List<string>();
                foreach (SmsPublishClass.ClientClass clientobj in SmsPublishClass._ClientList)
                {
                    clientname.Add(clientobj.ClientName);
                    if (!ClientListComboBox.Items.Contains(clientobj.ClientName))
                        ClientListComboBox.Items.Add(clientobj.ClientName);
                }
                if (ClientListComboBox.SelectedItem != null && clientname.Contains(ClientListComboBox.SelectedItem.ToString()) == false)
                {
                    ClientListComboBox.Text = "";
                    EmulatorStatusButton_Click(null, null);
                }
                for (int i = 0; i < ClientListComboBox.Items.Count; i++)
                {
                    if (clientname.Contains(ClientListComboBox.Items[i].ToString()) == false)
                        ClientListComboBox.Items.RemoveAt(i);
                }
            }
        }

        void tcpClient_SmsReceived(SmsClass Message)
        {
            Console.WriteLine(Message.ToString());
            InboxTableUpdate(Message);
        }

        void tcpClient_Connected()
        {
            CheckStateTime.Enabled = false;
            StatusUpdate("Phone Connection Established. Ready to run Sms Services");
            IPCPublisher.IsConnected = true;
            CommandClass ValueCommand = new CommandClass();
            ValueCommand.Type = CommandTypeEnum.SetValue;

            // set delete inbox settings
            ValueCommand.Name = "DeleteInbox";
            ValueCommand.Value = Properties.Settings.Default.DeleteInbox.ToString();
            tcpClient.SendMessage(ValueCommand.ToString());

            // set Admin Number
            ValueCommand.Name = "AdminNumber";
            ValueCommand.Value = Properties.Settings.Default.AdministratorNumber.Trim();
            tcpClient.SendMessage(ValueCommand.ToString());

            //set Admin inform option
            ValueCommand.Name = "InformAdmin";
            ValueCommand.Value = Properties.Settings.Default.InformAdmin.ToString();
            tcpClient.SendMessage(ValueCommand.ToString());

            //set BlockNonNumeric Numbers
            ValueCommand.Name = "BlockNonNumberic";
            ValueCommand.Value = Properties.Settings.Default.BlockNonNumeric.ToString();
            tcpClient.SendMessage(ValueCommand.ToString());

            if (Properties.Settings.Default.ProcessInbox == true)
            {
                CommandClass ProcessCommand = new CommandClass();
                ProcessCommand.Type = CommandTypeEnum.GetInboxMessage;
                if(Properties.Settings.Default.RememberLastAccess == true)
                    ProcessCommand.Value = Properties.Settings.Default.LastAccessTime.Ticks.ToString();
                else
                    ProcessCommand.Value = DateTime.Now.AddYears(-5).Ticks.ToString();
                tcpClient.SendMessage(ProcessCommand.ToString());
            }
            CommandClass FilterCommand = new CommandClass();
            FilterCommand.Type = CommandTypeEnum.StartFilter;
            tcpClient.SendMessage(FilterCommand.ToString());
            AgentTrayIcon.Icon = Properties.Resources.connected2;
        }

        void tcpClient_Disconnected(bool p)
        {
            AgentTrayIcon.Icon = Properties.Resources.disconnected2;
            if (IsActiveSyncConnected == 1 && p == true)
            {
                Invoke(new ReStartDelegate(ReStartTimer));
                StatusUpdate("Phone Client Disconnected");
            }
            IPCPublisher.IsConnected = false;
        }

        void tcpClient_MessageReceived(string Message)
        {
        }

        void objDccManSink_ConnectedToIPaddress(int dwIpAddr)
        {
            StatusUpdate("ActiveSync Connection Established");
            Interlocked.Exchange(ref IsActiveSyncConnected, 1);
            Application.DoEvents();
            Int16 port = HelperClass.GetTcpPort();
            if (port == -1)
            {
                StatusUpdate("Smartphone client not found!!");
                return;
            }
            else if (port != Properties.Settings.Default.TcpPort)
            {
                Properties.Settings.Default.TcpPort = port;
                Properties.Settings.Default.Save();
            }
            IPAddress DeviceAddress = new IPAddress(dwIpAddr);
            tcpClient.InitTcpClientClass(DeviceAddress, Properties.Settings.Default.TcpPort);
            if (tcpClient.Connect() == false)
                Invoke(new ReStartDelegate(ReStartTimer));
        }


        void objDccManSink_Disconnect()
        {
            Interlocked.Exchange(ref IsActiveSyncConnected, 0);
            StatusUpdate("ActiveSync Disconnected");
        }

        void objDccManSink_Active()
        {
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            Interlocked.Exchange(ref IsActiveSyncConnected, 0);
            if (tcpClient != null)
                tcpClient.Disconnect(false);
            if (AdviceReturn != 0)
                objIDccMan.Unadvise(AdviceReturn);
            if (ipc != null)
                ChannelServices.UnregisterChannel(ipc);
            Properties.Settings.Default.Upgrade();
        }

        private void ReStartTimer()
        {
            CheckStateTime.Start();
        }

        private void CheckStateTime_Tick(object sender, EventArgs e)
        {
            if (IsActiveSyncConnected == 1 && tcpClient != null && tcpClient.IsConnected == 0)
            {
                CheckStateTime.Stop();
                StatusUpdate("Connecting with Phone Client");
                if (HelperClass.StartSmartPhoneClient())
                    Thread.Sleep(3000);
                tcpClient.InitTcpClientClass();
                CheckStateTime.Enabled = !tcpClient.Connect(); // vibhore
            }
            else
                CheckStateTime.Stop();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            // TODO: This line of code loads data into the 'sMSServerDataSet.Sms_BlockedList' table. You can move, or remove it, as needed.
            this.sMS_BlockedListTableAdapter.Fill(this.sMSServerDataSet.Sms_BlockedList);
            // TODO: This line of code loads data into the 'sMSServerDataSet.Sms_BlockedList' table. You can move, or remove it, as needed.
            this.sMS_InboxTableAdapter.Fill(this.sMSServerDataSet.Sms_Inbox);
            // TODO: This line of code loads data into the 'sMSServerDataSet.Sms_Sent' table. You can move, or remove it, as needed.
            this.sMS_SentTableAdapter.Fill(this.sMSServerDataSet.Sms_Sent);
        }

        private void bindingNavigatorDeleteItem_Click(object sender, EventArgs e)
        {
            sMS_InboxTableAdapter.Update(sMSServerDataSet.Sms_Inbox);
        }

        private void AgentForm_Resize(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                AgentTrayIcon.Visible = true;
                this.Hide();
            }
        }

        private void AgentTrayIcon_Click(object sender, EventArgs e)
        {
            this.Show();
            this.WindowState = FormWindowState.Normal;
            AgentTrayIcon.Visible = false;
            this.Focus();
        }

        // 
        // Emulator Functions
        //

        private void SmsMessageBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == 13)
                SendButton_Click(sender, e);
        }

        private void SendButton_Click(object sender, EventArgs e)
        {
            if (ClientListComboBox.SelectedItem != null)
            {
                EmulatorClientName = ClientListComboBox.SelectedItem.ToString();
                SmsClass Message = new SmsClass();
                Message.Body = SmsMessageBox.Text.Trim();
                Message.Time = DateTime.Now;
                Message.Number = FromNumberBox.Text.Trim();
                SmsResponseClass Response = IPCPublisher.Server2Client_SmsReceived(ClientListComboBox.SelectedItem.ToString(), Message, true);
                string str = String.Format("\\b Received:\\b0 {0} " +
                            "\\par\\b From:\\b0 {1}" +
                            "\\par\\b To:\\b0 {2}" +
                            "\\par\\b Message({3})\\b0\\par {4}" +
                            "\\par __________________________________", Message.Time, Message.Number, EmulatorClientName,Message.Body.Length, Message.Body);
                str = str.Replace("\n", "\\par ");
                MessageHistoryUpdate(str);
                ProcessResponseSms(Response);
            }
        }

        private void SmsMessageBox_TextChanged(object sender, EventArgs e)
        {
            MessageLengthBox.Text = "Length : " + SmsMessageBox.Text.Trim().Length;
        }

        void MessageHistoryUpdate(string Message)
        {
            if (InvokeRequired)
            {
                Invoke(new MessageHistoryUpdateDelegate(MessageHistoryUpdate), new object[] { Message });
            }
            else
            {
                string rtf = "";
                if (MessageHistoryBox.Text == "")
                    rtf = MessageHistoryBox.Rtf.Trim().Substring(0, MessageHistoryBox.Rtf.Trim().Length - 1).Trim().Replace("\\pard", "").Replace("\\par", "");
                else
                    rtf = MessageHistoryBox.Rtf.Trim().Substring(0, MessageHistoryBox.Rtf.Trim().Length - 1).Trim();
                MessageHistoryBox.Rtf = rtf + Message + "}";
                MessageHistoryBox.SelectionStart = MessageHistoryBox.Text.Length;
                MessageHistoryBox.ScrollToCaret();
            }
        }

        void InboxTableUpdate(SmsClass Message)
        {
            if (InvokeRequired)
            {
                Invoke(new InboxTableUpdateDelegate(InboxTableUpdate), new object[] { Message });
            }
            else
            {
                try
                {
                    DataRowView myobject = (DataRowView)sMSInboxBindingSource.AddNew();
                    myobject["Body"] = Message.Body;
                    myobject["from"] = Message.Number;
                    myobject["id"] = Message.MessageID;
                    myobject["time"] = Message.Time;
                    this.sMS_InboxTableAdapter.InboxInsertSms(Message.Number, Message.Time, Message.Body, Message.MessageID);
                    Properties.Settings.Default.LastAccessTime = Message.Time;
                    Properties.Settings.Default.Save();
                    if (Properties.Settings.Default.GlobalBlockedList == true && sMS_BlockedListTableAdapter.IsBlocked(Message.Number) == 0)
                    {
                        SmsResponseClass response = IPCPublisher.Server2Client_SmsReceived(EmulatorClientName, Message, false);
                        ProcessResponseSms(response);
                        
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(string.Format("Error Code:002({0})",ex.Message)); 
                }

            }
        }

        void ProcessResponseSms(SmsResponseClass Response)
        {
            if (Response == null || Response.Type == ResponseClassEnum.Ignore)
                return;
            else
            {
                for (int i = 0; i < Response.Count; i++)
                {
                    IPCPublisher_OnClientSendSms(Response[i].ClientName, Response[i]);
                }
            }
        }

        internal void SentTableUpdate(String ClientName, SmsClass Message)
        {
            if (InvokeRequired)
            {
                Invoke(new SentTableUpdateDelegate(SentTableUpdate), new object[] {ClientName, Message });
            }
            else
            {
                try
                {
                    DataRowView myobject = (DataRowView)sMSSentBindingSource.AddNew();
                    myobject["Body"] = Message.Body;
                    myobject["fromclient"] = ClientName;
                    myobject["id"] = Message.MessageID;
                    myobject["time"] = Message.Time;
                    myobject["to"] = Message.Number;
                    myobject["Status"] = 0;
                    this.sMS_SentTableAdapter.SentInsertSms(ClientName, Message.Number, Message.Body, Message.Time, 0, Message.MessageID);
                    tcpClient.SendMessage(Message.ToString());
                }
                catch (Exception ex)
                {
                    MessageBox.Show("SentTableUpdate:" +  ex.Message);
                }
            }
        }

        void DeliveryReportStatusUpdate(DeliveryReportClass Report)
        {
            if (InvokeRequired)
            {
                Invoke(new DeliveryReportStatusUpdateDelegate(DeliveryReportStatusUpdate), new object[] {Report });
            }
            else
            {
                try
                {
                    string clientname = sMS_SentTableAdapter.GetClientNamebyID(Report.MessageID);
                    if (clientname != null)
                    {

                        sMS_SentTableAdapter.SentStatusUpdateSms(1, Report.MessageID);
                        IPCPublisher.Server2Client_DeliveryReportReceived(clientname, Report, true);
                        foreach (DataGridViewRow dr in SentdataGridView.Rows)
                        {
                            if (dr.Cells["ID"].Value.ToString() == Report.MessageID.ToString())
                            {
                                dr.Cells["statusDataGridViewTextBoxColumn"].Value = 1;
                                break;
                            }
                        }
                        //dataGridView1.get
                        //this.sMS_SentTableAdapter.Fill(sMSServerDataSet.Sms_Sent);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("DeliveryReportUpdate:" + ex.Message);
                }
            }
        }

        private void EmulatorStatusButton_Click(object sender, EventArgs e)
        {
            if (EmulatorStarted == false && sender!=null)
            {
                if (ClientListComboBox.SelectedItem != null)
                {
                    EmulatorStatusButton.Text = "Stop Emulator";
                    EmulatorClientName = ClientListComboBox.SelectedItem.ToString();
                    SendButton.Enabled = true;
                    SmsMessageBox.Enabled = true;
                    FromNumberBox.Enabled = true;
                    EmulatorStarted = true;
                }
                else
                {
                    MessageBox.Show("Please select a Sms service name...");
                }
            }
            else
            {
                EmulatorStatusButton.Text = "Start Emulator";
                EmulatorClientName = null;
                SendButton.Enabled = false;
                SmsMessageBox.Enabled = false;
                FromNumberBox.Enabled = false;
                EmulatorStarted = false;
            }
        }

        private void label1_Click(object sender, EventArgs e)
        {
            bool response = IPCPublisher.IsClientConnected();
            //if(response == false)
            ClientComboBoxUpdate(); 
        }

        private void clearToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageHistoryBox.Clear();
        }

        private void IpcTimer_Tick(object sender, EventArgs e)
        {
            bool response = IPCPublisher.IsClientConnected();
            if (response == false)
                ClientComboBoxUpdate();
        }

        private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (AboutForm == null || AboutForm.IsDisposed == true)
                AboutForm = new AboutBox();
            AboutForm.Show();
        }

        private void optionsToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (ConfigForm == null || ConfigForm.IsDisposed == true)
            {
                ConfigForm = new Config();
                ConfigForm.Tag = this;
            }
            this.Hide();
            ConfigForm.Show();
        }

        private void exitToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void InboxdataGridView_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
        {
            DataGridViewRow dr = e.Row;
            sMS_InboxTableAdapter.Delete((Guid)dr.Cells["MessageID"].Value);
        }

        private void sendSmsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (sendSmsForm == null || sendSmsForm.IsDisposed == true)
            {
                sendSmsForm = new SendSmsForm();
                sendSmsForm.Tag = this;
            }
            this.Hide();
            sendSmsForm.Show();
        }

        private void SentdataGridView_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
        {
            DataGridViewRow dr = e.Row;
            sMS_SentTableAdapter.Delete((Guid)dr.Cells["ID"].Value);
        }

     }
}